home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.1v2 SDK / Sample Code / CPU meter ƒ / .c / CPU_Meter.c next >
Encoding:
C/C++ Source or Header  |  2000-05-13  |  54.9 KB  |  2,195 lines  |  [TEXT/CWIE]

  1. /**\
  2. |**|    CPU_Meter.c
  3. \**/
  4.  
  5. /**\
  6. |**| ==============================================================================
  7. |**| COMPILER DIRECTIVES
  8. |**| ==============================================================================
  9. \**/
  10.  
  11. #define kMaxTasks                64
  12. #define kMaxCPUs                16    // Yea, I wish!
  13.  
  14. #define SystemSevenOrLater        1
  15. #define DEBUGSTRINGS             1
  16.  
  17. #define USE_COLLECTION_TASK        1
  18. #define USE_OFFSCREEN            0
  19. #define USE_ZOOM_WINDOW            0
  20.  
  21. #define kInfoMPTaskWeight        9999
  22.  
  23. /**\
  24. |**| ==============================================================================
  25. |**| INCLUDES
  26. |**| ==============================================================================
  27. \**/
  28.  
  29. #ifndef USE_PRECOMPILED_HEADER
  30. #include "MyHeaders.i"
  31. #endif
  32.  
  33. #include <Devices.h>
  34. #include <Fonts.h>
  35. #include <CodeFragments.h>
  36. #include <Dialogs.h>
  37. #include <DiskInit.h>
  38. #include <LowMem.h>
  39. #include <math.h>
  40. #include <Math64.h>
  41. #include <Multiprocessing.h>
  42. #include <PLStringFuncs.h>
  43. #include <Sound.h>
  44. #include <Traps.h>
  45. #include <Threads.h>
  46. #include <MacWindows.h>
  47.  
  48. #include <stdio.h>
  49. #include <string.h>
  50.  
  51. #include "MPInfoLib.h"
  52. #if USE_OFFSCREEN
  53. #include "Offscreen.h"
  54. #endif USE_OFFSCREEN
  55. #include "Preferences.h"
  56.  
  57. #if __profile__
  58. #include <Profiler.h>
  59. #endif
  60.  
  61. /**\
  62. |**| ==============================================================================
  63. |**| TYPEDEFS, STRUCTS, DEFINES, ENUMS, ETC.
  64. |**| ==============================================================================
  65. \**/
  66.  
  67. #if DEBUGSTRINGS
  68. #    define DEBUGSTR(x) DebugStr((x))
  69. #    define LOGSTRING(b,s) if (b) do {DEBUGSTR(s);} while (false);
  70. #else
  71. #    define DEBUGSTR(x)
  72. #    define LOGSTRING(b,s)
  73. #endif
  74.  
  75. enum
  76. {
  77.     mAppleMenu = 128,
  78.         iAboutBox = 1,
  79.     mFileMenu = 129,
  80.         iQuit = 1,
  81.     mEditMenu = 130,
  82.         iUndo = 1,
  83.         iCut = 3,
  84.         iCopy = 4,
  85.         iPaste = 5,
  86.         iClear = 6,
  87.         iDuplicate = 8,
  88.         iSelectAll = 9,
  89.     mShow = 131,
  90.         iProcID = 1,
  91.         iTaskID = 2,
  92.         iName = 3,
  93.         iQueue = 4,
  94.         iCPUTime = 5,
  95.         iDelta = 6,
  96.         iPercent = 7,
  97.         iPreemptions = 8,
  98.         iDeltaPreemptions = 9,
  99.         iWeight = 10,
  100.         iBar = 11,
  101.         iSubTotals = 12,
  102.         iTotals = 13,
  103.     mInterval = 132,
  104.         iPointFive = 1,
  105.         iOne = 2,
  106.         iTwo = 3,
  107.         iFive = 4,
  108.         iTen = 5,
  109.         iTwenty = 6,
  110.         iThirty = 7,
  111.         iMinute = 8
  112. };
  113.  
  114. #define kTextSize 12
  115.  
  116. typedef struct MyTaskStruct
  117. {
  118.     MPProcessID        fProcID;
  119.     MPTaskID        fTaskID;
  120.     MPTaskInfo        fInfo;
  121.     MPTaskInfo        fLast;
  122.     float            fPercent;
  123.     Boolean            fValid;
  124. } MyTaskRec, * MyTaskPtr, ** MyTaskHdl;
  125.  
  126. #define RECT_WIDTH(r) ((r).right - (r).left)
  127. #define RECT_HEIGHT(r) ((r).bottom - (r).top)
  128.  
  129. #ifndef MIN
  130. #    define ABS(x)    ((x) >= 0 ? (x) : -(x))
  131. #    define MIN(a,b) ((a) < (b) ? (a) : (b))
  132. #    define MAX(a,b) ((a) > (b) ? (a) : (b))
  133. #    define PIN(a,b,c) MIN(MAX((a),(b)),(c))
  134. #endif
  135.  
  136. #if CALL_NOT_IN_CARBON
  137.     #define EnableMenuItem(m,i) EnableItem((m),(i))
  138.     #define InvalWindowRect(w,r) InvalRect(r)
  139.     #define C2PSTR(s) C2PStr((Ptr) s)
  140. #else
  141. //    #define C2PSTR(s) CopyCStringToPascal((const char *) s,(Str255) s)
  142. //    #define C2PSTR(s) CopyCStringToPascal(s,(Str255) s)
  143.     #define C2PSTR(s) CopyCStringToPascal((const char *) s,s)
  144. #endif
  145.  
  146. /**\
  147. |**| ==============================================================================
  148. |**| EXPORTED FUNCTION PROTOTYPES
  149. |**| ==============================================================================
  150. \**/
  151.  
  152. /**\
  153. |**| ==============================================================================
  154. |**| PRIVATE FUNCTION PROTOTYPES
  155. |**| ==============================================================================
  156. \**/
  157.  
  158. static OSStatus Init_Mac(void);
  159. static OSStatus Open_Window(const Rect* pRect);
  160. static void Handle_Command(const long ms);
  161. static void Handle_Event(const EventRecord* pEventPtr);
  162. static void Handle_NullEvent(const EventRecord* pEventPtr);
  163. static void Handle_MouseEvent(const EventRecord* pEventPtr);
  164. static void Handle_KeyEvent(const char key,const SInt16 modifiers);
  165. static void Handle_UpdateEvent(WindowPtr updateWindowP);
  166. static void Handle_ActivateEvent(WindowPtr updateWindowP);
  167. static void Handle_DiskEvent(const long message);
  168. static void Handle_OSEvent(const long message);
  169.  
  170. static Boolean SetUp_MenuBar(void);
  171. static void Adjust_MenuItems(void);
  172.  
  173. static void Handle_ContentClick(WindowPtr pWindowPtr,const EventRecord* pEventPtr);
  174.  
  175. static OSStatus Collect_Info(void);
  176. static void Draw_Info(void);
  177.  
  178. static UInt64 AbsoluteToMilliseconds(const AbsoluteTime t);
  179. static OSStatus save_prefs(void);
  180.  
  181. static RGBColor Blend_RGBColors(
  182.     const RGBColor pRGBColorA,
  183.     const RGBColor pRGBColorB,
  184.     const float pBlend);
  185.  
  186. #if 0
  187. static void Zoom_Window(WindowPtr theWindow,
  188.                         const short zoomDir,
  189.                         const short hMax,
  190.                         const short vMax);
  191. static void Grow_WindowGrid(WindowPtr theWindow);
  192. static void Drag_WindowGrid(WindowPtr win,const Point pt);
  193. #endif
  194.  
  195. #if USE_COLLECTION_TASK
  196. static OSStatus InfoTask(void *parameter);
  197. #endif USE_COLLECTION_TASK
  198.  
  199. /**\
  200. |**| ==============================================================================
  201. |**| PRIVATE GLOBALS
  202. |**| ==============================================================================
  203. \**/
  204.  
  205. static WindowPtr gWindowPtr = nil;
  206. static Rect gWindowRect;
  207. static Boolean gInBackGround = false;
  208. static Boolean gQuitFlag = false;
  209. #if USE_OFFSCREEN
  210. static Window_OffscreenPtr gOffscreenPtr = nil;
  211. #endif USE_OFFSCREEN
  212.  
  213. static SInt32 gNextTicks = 0;
  214.  
  215. static MyTaskRec gMyTaskRecs[kMaxTasks];
  216. static UInt32 gMyTaskRecCount = 0;
  217.  
  218. static UInt32 gIntervals[] = {30, 60, 120, 300, 600, 1200, 1800, 3600};
  219.  
  220. static const RGBColor 
  221.     blackRGBColor     =    {0x0000, 0x0000, 0x0000},
  222.     blueRGBColor    =    {0x0000, 0x0000, 0xFFFF},
  223.     ltBlueRGBColor     =     {0x7FFF, 0x7FFF, 0xFFFF},
  224.     dkBlueRGBColor     =     {0x0000, 0x0000, 0x7FFF},
  225.     redRGBColor     =    {0xFFFF, 0x0000, 0x0000},
  226.     ltGreenRGBColor =     {0x7FFF, 0xFFFF, 0x7FFF},
  227.     greenRGBColor     =     {0x0000, 0xFFFF, 0x0000},
  228.     dkGreenRGBColor =    {0x0000, 0x7FFF, 0x0000},
  229.     yellowRGBColor     =    {0xFFFF, 0xFFFF, 0x0000},
  230.     dkGrayRGBColor     =    {0x4444, 0x4444, 0x5444},
  231.     mdGrayRGBColor     =    {0x8888, 0x8888, 0x9888},
  232.     ltGrayRGBColor     =    {0xaaaa, 0xaaaa, 0xbaaa},
  233.     whiteRGBColor    =      {0xFFFF, 0xFFFF, 0xFFFF};
  234.  
  235. static const RGBColor greenRGBColors[] = {
  236.     {13107, 26214, 0},
  237.     {39371, 54248, 15934},
  238.     {46517, 57568, 16448},
  239.     {52685, 60909, 28013},
  240.     {56283, 65021, 30069},
  241.     {60909, 65535, 47031}
  242. };
  243.  
  244. static const RGBColor dkGreenRGBColors[] = {
  245.     {6554, 131707, 0},
  246.     {19686, 27124, 7967},
  247.     {23259, 28784, 8224},
  248.     {26343, 30455, 14007},
  249.     {28142, 32511, 15035},
  250.     {30455, 32768, 23516}
  251. };
  252.  
  253. static const RGBColor grayRGBColors[] = {
  254.     {21845, 21845, 21845},
  255.     {34952, 34952, 34952},
  256.     {43690, 43690, 43690},
  257.     {48059, 48059, 48059},
  258.     {56797, 56797, 56797},
  259.     {61166, 61166, 61166}
  260. };
  261.  
  262. static Preferences gPreferences;
  263.  
  264. static EventRecord gTheEvent;                    // from the main event loop
  265. static Boolean gHasColorQD = true;
  266. static Point gGridSize = {8, 4};
  267.  
  268. #if USE_COLLECTION_TASK
  269. static MPSemaphoreID    gInfoReadyMPSemaphoreID = kInvalidID;
  270. static MPQueueID        gMPNotifyQueueID = kInvalidID;
  271. static MPTaskID            gInfoMPTaskID = kInvalidID;
  272. static OSErr            gMPTaskErr = noErr;
  273. #endif USE_COLLECTION_TASK
  274.  
  275. /**\
  276. |**| ==============================================================================
  277. |**| PRIVATE FUNCTIONS
  278. |**| ==============================================================================
  279. \**/
  280.  
  281. void main(void)
  282. {
  283. #if __profile__
  284.     if (!ProfilerInit(collectDetailed, bestTimeBase, 20, 5))
  285.     {
  286. #endif
  287.  
  288.         if (!Init_Mac() && SetUp_MenuBar())
  289.         {
  290.             do
  291.             {
  292.                 InitCursor();
  293.                 WaitNextEvent(everyEvent, &gTheEvent, 10, nil);
  294.                 Handle_Event(&gTheEvent);
  295.             } while (!gQuitFlag);
  296.         }
  297.  
  298. #if __profile__
  299.     }
  300.     ProfilerDump("\pCPU_Meter.dump");
  301.     ProfilerTerm();
  302. #endif
  303.  
  304. }
  305.  
  306. /**\
  307. |**|    Initialize toolboxes
  308. \**/
  309.  
  310. static OSStatus Init_Mac(void)
  311. {
  312.     OSStatus anErr;
  313. #if !TARGET_API_MAC_CARBON
  314.     SysEnvRec theWorld;
  315.     //
  316.     //    Test the computer to be sure we can do color.  
  317.     //    If not we would crash, which would be bad.  
  318.     //    If we can’t run, just beep and exit.
  319.     //
  320.     anErr = SysEnvirons(1, &theWorld);
  321.     if (theWorld.hasColorQD == false)
  322.     {
  323.         SysBeep(50);
  324.         ExitToShell();                            // If no color QD, we must leave.
  325.     }
  326.  
  327.     MaxApplZone();
  328.     InitGraf(&(qd.thePort));
  329.     InitFonts();
  330.     InitWindows();
  331.     InitMenus();
  332.     TEInit();
  333.     InitDialogs(nil);
  334. #endif
  335.     //    InitContextualMenus();
  336. #if TARGET_API_MAC_CARBON
  337.     {
  338.         UInt32 tUInt32;
  339.         GetDateTime(&tUInt32);
  340.         SetQDGlobalsRandomSeed(tUInt32);
  341.     }
  342. #else
  343.     GetDateTime((unsigned long*) & qd.randSeed);
  344. #endif TARGET_API_MAC_CARBON
  345.  
  346.     gWindowPtr = nil;                            // just to be sure
  347.  
  348.     gPreferences.fVersion = -1; // illegal value
  349.     anErr = ReadPreferences(&gPreferences);
  350.     if (noErr == anErr)
  351.         gWindowRect = gPreferences.fWindowRect;
  352.  
  353.     if (gPreferences.fVersion != kPrefsVersion)
  354.     {
  355. #if TARGET_API_MAC_CARBON
  356.         BitMap        screenBits;
  357.         gWindowRect = GetQDGlobalsScreenBits(&screenBits)->bounds;
  358. #else
  359.         gWindowRect = qd.screenBits.bounds;
  360. #endif TARGET_API_MAC_CARBON
  361.         gWindowRect.top += GetMBarHeight() + 1;
  362.         InsetRect(&gWindowRect, 100, 100);
  363.  
  364.         gPreferences.fVersion = kPrefsVersion;
  365.         gPreferences.fInterval = gIntervals[1];
  366.         gPreferences.fShowProcID = false;
  367.         gPreferences.fShowTaskID = false;
  368.         gPreferences.fShowName = true;
  369.         gPreferences.fShowQueue = true;
  370.         gPreferences.fShowCPUTime = false;
  371.         gPreferences.fShowDeltaCPU = true;
  372.         gPreferences.fShowPercent = true;
  373.         gPreferences.fShowPreemptions = false;
  374.         gPreferences.fShowDeltaPreemptions = true;
  375.         gPreferences.fShowWeight = true;
  376.         gPreferences.fShowBar = true;
  377.         gPreferences.fShowSubTotals = true;
  378.         gPreferences.fShowTotals = true;
  379.         save_prefs();
  380.     }
  381.  
  382.     Open_Window(&gWindowRect);
  383.  
  384. #if USE_COLLECTION_TASK
  385.  
  386.     if (!MPLibraryIsLoaded())
  387.         return unimpErr;
  388.  
  389.     anErr = MPCreateSemaphore(256,0,&gInfoReadyMPSemaphoreID);
  390.     if (noErr != anErr) return anErr;
  391.  
  392.     anErr = MPCreateQueue(&gMPNotifyQueueID);
  393.     if (noErr != anErr) return anErr;
  394.  
  395.     anErr = MPCreateTask(InfoTask,nil,0,gMPNotifyQueueID,nil,&gMPTaskErr,0,&gInfoMPTaskID);
  396.     if (noErr != anErr) return anErr;
  397.  
  398.     anErr = MPSetTaskWeight(gInfoMPTaskID,kInfoMPTaskWeight);
  399.     if (noErr != anErr) return anErr;
  400.  
  401. #endif USE_COLLECTION_TASK
  402.  
  403.     return noErr;
  404. }    // Init_Mac
  405.  
  406.  
  407. /**\
  408. |**|    Initialize toolboxes
  409. \**/
  410.  
  411. static OSStatus Open_Window(const Rect* pRect)
  412. {
  413.     //
  414.     //    Make a new window for drawing in, and it must be a color window.  
  415.     //    The window is full screen size, made smaller to make it more visible.
  416.     //
  417.  
  418.     gWindowPtr = NewCWindow(nil, pRect, "\pCPU Meter", true, zoomDocProc, (WindowPtr) - 1, false, 0);
  419.  
  420.     gWindowRect = *pRect;
  421.     OffsetRect(&gWindowRect, -gWindowRect.left, -gWindowRect.top);
  422.  
  423.     SetPortWindowPort(gWindowPtr);                        // set window to current graf port
  424.     TextSize(kTextSize);                        // smaller font for drawing.
  425.  
  426.     {
  427.         short familyID;
  428.         GetFNum("\pMonaco", &familyID);
  429.         TextFont(familyID);
  430.     }
  431.     return noErr;
  432. }
  433.  
  434. /**\
  435. |**|    Setup menu bar
  436. \**/
  437.  
  438. static Boolean SetUp_MenuBar(void)
  439. {
  440.     Boolean result = false;
  441.     Handle mBar = GetNewMBar(128);                // handle to menu bar
  442.  
  443.     if (!ResError() && mBar)
  444.     {
  445.         SetMenuBar(mBar);
  446. #if !TARGET_API_MAC_CARBON
  447.         AppendResMenu(GetMenuHandle(128), 'DRVR');
  448. #endif !TARGET_API_MAC_CARBON
  449.         DrawMenuBar();
  450.         ReleaseResource(mBar);
  451.         result = true;
  452.     }
  453.     return result;
  454. }
  455.  
  456. /**\
  457. |**|    Adjust menu items
  458. \**/
  459.  
  460. static void Adjust_MenuItems(void)
  461. {
  462.     MenuHandle tMenuHdl = GetMenuHandle(mShow);
  463.     if (tMenuHdl)
  464.     {
  465.         CheckMenuItem(tMenuHdl, iProcID, gPreferences.fShowProcID);
  466.         CheckMenuItem(tMenuHdl, iTaskID, gPreferences.fShowTaskID);
  467.         CheckMenuItem(tMenuHdl, iName, gPreferences.fShowName);
  468.         CheckMenuItem(tMenuHdl, iQueue, gPreferences.fShowQueue);
  469.         CheckMenuItem(tMenuHdl, iCPUTime, gPreferences.fShowCPUTime);
  470.         CheckMenuItem(tMenuHdl, iDelta, gPreferences.fShowDeltaCPU);
  471.         CheckMenuItem(tMenuHdl, iPercent, gPreferences.fShowPercent);
  472.         CheckMenuItem(tMenuHdl, iPreemptions, gPreferences.fShowPreemptions);
  473.         CheckMenuItem(tMenuHdl, iDeltaPreemptions, gPreferences.fShowDeltaPreemptions);
  474.         CheckMenuItem(tMenuHdl, iWeight, gPreferences.fShowWeight);
  475.         CheckMenuItem(tMenuHdl, iBar, gPreferences.fShowBar);
  476.         CheckMenuItem(tMenuHdl, iSubTotals, gPreferences.fShowSubTotals);
  477.         CheckMenuItem(tMenuHdl, iTotals, gPreferences.fShowTotals);
  478.     }
  479.  
  480.     tMenuHdl = GetMenuHandle(mInterval);
  481.     if (tMenuHdl)
  482.     {
  483.         SInt32 index, count = CountMenuItems(tMenuHdl);
  484.         SInt32 interval = gPreferences.fInterval;
  485.         SInt32 value;
  486.         Boolean first = true;
  487.  
  488.         for (index = 1; index <= count; index++)
  489.         {
  490.             value = gIntervals[index - 1];
  491.  
  492.             EnableMenuItem(tMenuHdl, index);
  493.  
  494.             if (value < interval)
  495.                 CheckMenuItem(tMenuHdl, index, false);
  496.             else
  497.             {
  498.                 CheckMenuItem(tMenuHdl, index, first);
  499.                 if (first)
  500.                     gPreferences.fInterval = value;
  501.                 first = false;
  502.             }
  503.         }
  504.     }
  505. }
  506.  
  507. /**\
  508. |**|    Do menu command
  509. \**/
  510.  
  511. static void Handle_Command(const long ms)
  512. {
  513.     short menuID = ms >> 16,
  514.     menuItem = ms & 0xFFFF;
  515.  
  516.     switch (menuID)
  517.     {
  518.         case mAppleMenu:
  519.             switch (menuItem)
  520.             {
  521.                 case iAboutBox:                    // Bring up alert for About.
  522.                     SysBeep(15);
  523.                     break;
  524.                 default:                        // All non-About items in this menu are DAs.
  525. #if CALL_NOT_IN_CARBON
  526.                     {
  527.                         Str255 daName;
  528.                         GetMenuItemText(GetMenuHandle(menuID), menuItem, daName);
  529.                         OpenDeskAcc(daName);
  530.                     }
  531. #endif CALL_NOT_IN_CARBON
  532.                     break;
  533.             }
  534.             break;
  535.         case mFileMenu:
  536.             switch (menuItem)
  537.             {
  538.                 case iQuit:
  539.                     gQuitFlag = true;
  540.                     break;
  541.             }
  542.             break;
  543.         case mEditMenu:
  544.             switch (menuItem)
  545.             {
  546.                 case iUndo:
  547.                     break;
  548.                 case iCut:
  549.                     break;
  550.                 case iCopy:
  551.                     break;
  552.                 case iPaste:
  553.                     break;
  554.                 case iClear:
  555.                     break;
  556.                 case iDuplicate:
  557.                     break;
  558.                 case iSelectAll:
  559.                     break;
  560.             }
  561.             break;
  562.         case mShow:
  563.             switch (menuItem)
  564.             {
  565.                 case iProcID:
  566.                     gPreferences.fShowProcID = !gPreferences.fShowProcID;
  567.                     break;
  568.                 case iTaskID:
  569.                     gPreferences.fShowTaskID = !gPreferences.fShowTaskID;
  570.                     break;
  571.                 case iName:
  572.                     gPreferences.fShowName = !gPreferences.fShowName;
  573.                     break;
  574.                 case iQueue:
  575.                     gPreferences.fShowQueue = !gPreferences.fShowQueue;
  576.                     break;
  577.                 case iCPUTime:
  578.                     gPreferences.fShowCPUTime = !gPreferences.fShowCPUTime;
  579.                     break;
  580.                 case iDelta:
  581.                     gPreferences.fShowDeltaCPU = !gPreferences.fShowDeltaCPU;
  582.                     break;
  583.                 case iPercent:
  584.                     gPreferences.fShowPercent = !gPreferences.fShowPercent;
  585.                     break;
  586.                 case iPreemptions:
  587.                     gPreferences.fShowPreemptions = !gPreferences.fShowPreemptions;
  588.                     break;
  589.                 case iDeltaPreemptions:
  590.                     gPreferences.fShowDeltaPreemptions = !gPreferences.fShowDeltaPreemptions;
  591.                     break;
  592.                 case iWeight:
  593.                     gPreferences.fShowWeight = !gPreferences.fShowWeight;
  594.                     break;
  595.                 case iBar:
  596.                     gPreferences.fShowBar = !gPreferences.fShowBar;
  597.                     break;
  598.                 case iSubTotals:
  599.                     gPreferences.fShowSubTotals = !gPreferences.fShowSubTotals;
  600.                     break;
  601.                 case iTotals:
  602.                     gPreferences.fShowTotals = !gPreferences.fShowTotals;
  603.                     break;
  604.             }
  605.             gNextTicks = TickCount();            // make it update now
  606.             save_prefs();
  607.             break;
  608.         case mInterval:
  609.             switch (menuItem)
  610.             {
  611.                 case iPointFive:
  612.                 case iOne:
  613.                 case iTwo:
  614.                 case iFive:
  615.                 case iTen:
  616.                 case iTwenty:
  617.                 case iThirty:
  618.                 case iMinute:
  619.                     gPreferences.fInterval = gIntervals[menuItem - 1];
  620.                     gNextTicks = TickCount();    // make it update now
  621.                     save_prefs();
  622.                 default:
  623.                     break;
  624.             }
  625.     }
  626. }
  627.  
  628. /**\
  629. |**|    Handle event
  630. \**/
  631.  
  632. static void Handle_Event(const EventRecord* pEventPtr)
  633. {
  634.     switch (pEventPtr->what)
  635.     {
  636.         case nullEvent:                            // 0
  637.             LOGSTRING(0, "\p|Handle_Event-I-Debug, nullEvent.;g");
  638.             Handle_NullEvent(pEventPtr);
  639.             break;
  640.         case mouseDown:                            // 1
  641.             LOGSTRING(0, "\p|Handle_Event-I-Debug, mouseDown.;g");
  642.             Handle_MouseEvent(pEventPtr);
  643.             break;
  644.         case mouseUp:                            // 2
  645.             LOGSTRING(0, "\p|Handle_Event-I-Debug, mouseUp.;g");
  646.             break;
  647.         case keyDown:                            // 3
  648.             LOGSTRING(0, "\p|Handle_Event-I-Debug, keyDown.;g");
  649.             goto dokey;
  650.             break;
  651.         case keyUp:                                // 4
  652.             LOGSTRING(0, "\p|Handle_Event-I-Debug, keyUp.;g");
  653.             break;
  654.         case autoKey:                            // 5
  655.             LOGSTRING(0, "\p|Handle_Event-I-Debug, autoKey.;g");
  656. dokey:        Handle_KeyEvent((char)(pEventPtr->message & charCodeMask), pEventPtr->modifiers);
  657.             break;
  658.         case updateEvt:                            // 6
  659.             LOGSTRING(0, "\p|Handle_Event-I-Debug, updateEvt.;g");
  660.             Handle_UpdateEvent((WindowPtr)pEventPtr->message);
  661.             break;
  662.         case diskEvt:                            // 7
  663.             LOGSTRING(0, "\p|Handle_Event-I-Debug, diskEvt.;g");
  664.             Handle_DiskEvent(pEventPtr->message);
  665.             break;
  666.         case activateEvt:                        // 8
  667.             LOGSTRING(0, "\p|Handle_Event-I-Debug, activateEvt.;g");
  668.             Handle_ActivateEvent((WindowPtr)pEventPtr->message);
  669.             break;
  670.         case osEvt:                                // 15
  671.             LOGSTRING(0, "\p|Handle_Event-I-Debug, osEvt.;g");
  672.             Handle_OSEvent(pEventPtr->message);
  673.             break;
  674.         case kHighLevelEvent:                    // 23
  675.             LOGSTRING(0, "\p|Handle_Event-I-Debug, kHighLevelEvent.;g");
  676.             AEProcessAppleEvent(pEventPtr);
  677.             break;
  678.         default:
  679.             LOGSTRING(0, "\p|pHandleEvent-I-Debug, UnHandled Event.;g");
  680.             break;
  681.     }
  682. }
  683.  
  684. /**\
  685. |**|    Do null event
  686. \**/
  687.  
  688. static void Handle_NullEvent(const EventRecord* pEventPtr)
  689. {
  690.     (pEventPtr);
  691.  
  692.     if (gWindowPtr)
  693.     {
  694.         GrafPtr savePort;
  695. #if !USE_COLLECTION_TASK
  696.         SInt32 nowTicks = TickCount();
  697. #endif USE_COLLECTION_TASK
  698.  
  699.         GetPort(&savePort);
  700.         SetPortWindowPort(gWindowPtr);
  701.  
  702. #if USE_COLLECTION_TASK
  703.         if (noErr == MPWaitOnQueue(gMPNotifyQueueID,nil,nil,nil,kDurationImmediate))
  704.             DebugStr("\p|Handle_NullEvent-I-Debug, gMPNotifyQueueID notification!;");
  705.  
  706.         if (noErr == MPWaitOnSemaphore(gInfoReadyMPSemaphoreID,kDurationImmediate))
  707. #else
  708.         if (nowTicks > gNextTicks)
  709. #endif USE_COLLECTION_TASK
  710.         {
  711. #if !USE_COLLECTION_TASK
  712.             gNextTicks = nowTicks + gPreferences.fInterval;
  713. #endif USE_COLLECTION_TASK
  714.             InvalWindowRect(gWindowPtr,&gWindowRect);
  715.         }
  716.         SetPort(savePort);
  717.     }
  718. }
  719.  
  720. /**\
  721. |**|    Do mousedown event
  722. \**/
  723.  
  724. static void Handle_MouseEvent(const EventRecord* pEventPtr)
  725. {
  726.     WindowPtr window;
  727.     short part;
  728.  
  729.     part = FindWindow(pEventPtr->where, &window);
  730.  
  731.     if (part != inContent)
  732.     {
  733. #if TARGET_API_MAC_CARBON
  734.         Cursor tCursor;
  735.         GetQDGlobalsArrow(&tCursor);
  736.         SetCursor(&tCursor);
  737. #else
  738.         SetCursor(&qd.arrow);
  739. #endif TARGET_API_MAC_CARBON
  740.     }
  741.  
  742.     switch (part)
  743.     {
  744.         case inContent:
  745.             Handle_ContentClick(window, pEventPtr);
  746.             if (window != FrontWindow())
  747.             {
  748.                 SelectWindow(window);
  749.                 //                HiliteWindows();
  750.             }
  751.             else
  752.                 break;
  753.  
  754.         case inDrag:
  755. #if 0
  756.             Drag_WindowGrid(window, pEventPtr->where);
  757. #else
  758. #if TARGET_API_MAC_CARBON
  759.             {
  760.                 BitMap        screenBits;
  761.                 DragWindow(window, pEventPtr->where, &GetQDGlobalsScreenBits(&screenBits)->bounds);
  762.             }
  763. #else
  764.             DragWindow(window, pEventPtr->where, &qd.screenBits.bounds);
  765. #endif
  766. #endif 0
  767.             save_prefs();
  768.             break;
  769.  
  770.         case inGoAway:
  771.             if (TrackGoAway(window, pEventPtr->where))
  772.             {
  773.                 save_prefs();
  774.  
  775.                 DisposeWindow(window);
  776.                 //                DisposeOneWindow(window,kClose);
  777.                 if (window == gWindowPtr)
  778.                     gWindowPtr = nil;
  779.             }
  780.             break;
  781.  
  782.         case inGrow:
  783.             {
  784. #if 0
  785.                 Grow_WindowGrid(window);
  786. #else
  787.                 if (window == FrontWindow())
  788.                 {
  789.                     RgnHandle tGrayRgnHdl = GetGrayRgn();
  790.                     Rect growLimits;
  791.                     long growResult;
  792. #if ACCESSOR_CALLS_ARE_FUNCTIONS
  793.                     GetRegionBounds(tGrayRgnHdl,&growLimits);
  794. #else
  795.                     growLimits = (*tGrayRgnHdl)->rgnBBox;
  796. #endif
  797.                     growResult = GrowWindow(window, pEventPtr->where, &growLimits);
  798.                     if (growResult)
  799.                     {
  800.                         SizeWindow(window, LoWord(growResult), HiWord(growResult), true);
  801. #if USE_OFFSCREEN
  802.                         if (nil != gOffscreenPtr)
  803.                             Close_Offscreen(gOffscreenPtr);
  804.                         gOffscreenPtr = nil;
  805. #endif USE_OFFSCREEN
  806.                     }
  807.                 } else
  808.                     SelectWindow(window);
  809. #endif
  810. #if ACCESSOR_CALLS_ARE_FUNCTIONS
  811.                 GetPortBounds(GetWindowPort(window),&gWindowRect);
  812. #else
  813.                 gWindowRect = window->portRect;
  814. #endif CALL_NOT_IN_CARBON
  815.                 save_prefs();
  816.             }
  817.             break;
  818.  
  819.         case inMenuBar:                            // Process mouse menu command (if any).
  820.             {
  821.                 long ms;
  822.  
  823.                 Adjust_MenuItems();
  824.                 ms = MenuSelect(pEventPtr->where);
  825.                 if (ms)
  826.                     Handle_Command(ms);
  827.                 HiliteMenu(0);                    // Unhighlight what MenuSelect hilited.
  828.             }
  829.             break;
  830. #if CALL_NOT_IN_CARBON
  831.         case inSysWindow:                        // Let the system handle the mouseDown.
  832.             SystemClick(pEventPtr, window);
  833.             break;
  834. #endif CALL_NOT_IN_CARBON
  835.         case inZoomIn:
  836.         case inZoomOut:
  837.             {
  838.                 if (window == FrontWindow())
  839.                 {
  840. #if USE_ZOOM_WINDOW
  841. #    if TARGET_API_MAC_CARBON
  842.                     BitMap        screenBits;
  843.                     Rect        zoomLimits = GetQDGlobalsScreenBits(&screenBits)->bounds;
  844. #    else
  845.                     Rect zoomLimits = qd.screenBits.bounds;
  846. #    endif TARGET_API_MAC_CARBON
  847.  
  848.                     Zoom_Window(window, part, RECT_WIDTH(zoomLimits), RECT_HEIGHT(zoomLimits));
  849. #else
  850.                     if (!TrackBox(window, pEventPtr->where, part))
  851.                         break;
  852.  
  853.                     ZoomWindow(window, part, false);
  854. #    if ACCESSOR_CALLS_ARE_FUNCTIONS
  855.                     GetPortBounds(GetWindowPort(gWindowPtr),&gWindowRect);
  856. #    else
  857.                     gWindowRect = gWindowPtr->portRect;
  858. #    endif
  859.                     save_prefs();
  860. #    if USE_OFFSCREEN
  861.                     if (nil != gOffscreenPtr)
  862.                         Close_Offscreen(gOffscreenPtr);
  863.                     gOffscreenPtr = nil;
  864. #    endif USE_OFFSCREEN
  865.                 } else
  866.                     SelectWindow(window);
  867. #endif 0
  868.             }
  869.             break;
  870.         default:
  871.             break;
  872.     }
  873. }
  874.  
  875. /**\
  876. |**|    Do key events
  877. \**/
  878.  
  879. static void Handle_KeyEvent(const char key,const SInt16 modifiers)
  880. {
  881.     if ((modifiers & cmdKey) != 0)
  882.     {
  883.         Adjust_MenuItems();
  884.         //        HandleMenuCommand(MenuKey(key));
  885.         Handle_Command(MenuKey(key));
  886.         HiliteMenu(0);                            // Unhighlight what MenuSelect hilited.
  887.     }
  888. }
  889.  
  890. /**\
  891. |**|    Do update events
  892. \**/
  893.  
  894. static void Handle_UpdateEvent(WindowPtr updateWindowP)
  895. {
  896.     GrafPtr savePort;
  897.  
  898.     GetPort(&savePort);
  899.     SetPortWindowPort(updateWindowP);
  900.     BeginUpdate(updateWindowP);
  901.  
  902.     if (updateWindowP == gWindowPtr)
  903.     {
  904.  
  905. #if !USE_COLLECTION_TASK
  906.         if (noErr != Collect_Info())
  907.             DebugStr("\p|CPU_Meter-I-Debug, Handle_UpdateEvent:Collect_Info() error.;");
  908. #endif USE_COLLECTION_TASK
  909.  
  910.         //        EraseRect(&gWindowRect);
  911. #if USE_OFFSCREEN
  912.         if (nil == gOffscreenPtr)
  913.             gOffscreenPtr = Open_Offscreen(gWindowPtr);
  914.         SetPort_Offscreen(gOffscreenPtr);            
  915. #endif USE_OFFSCREEN
  916.         Draw_Info();
  917. #if USE_OFFSCREEN
  918.         Copy_Onscreen(gOffscreenPtr);
  919. #endif USE_OFFSCREEN
  920.     }
  921. #if TARGET_API_MAC_CARBON
  922.     {
  923.         RgnHandle tRgnHdl = nil;
  924.  
  925.         GetPortVisibleRegion(GetWindowPort(updateWindowP),tRgnHdl);
  926.         UpdateControls(updateWindowP, tRgnHdl);
  927.     }
  928. #else
  929.     UpdateControls(updateWindowP, updateWindowP->visRgn);
  930. #endif TARGET_API_MAC_CARBON
  931.  
  932.     DrawGrowIcon(updateWindowP);
  933.     EndUpdate(updateWindowP);
  934.  
  935.     SetPort(savePort);
  936. }
  937.  
  938. /**\
  939. |**|    Do disk events
  940. \**/
  941.  
  942. static void Handle_DiskEvent(const long message)
  943. {
  944. #if CALL_NOT_IN_CARBON
  945.     Point dialogLocation = {100, 100};
  946.  
  947.     if ((message & 0xFFFF0000) != noErr)
  948.     {
  949.         DIBadMount(dialogLocation, message);
  950.     }
  951. #else
  952.     (message);
  953. #endif CALL_NOT_IN_CARBON
  954. }
  955.  
  956. /**\
  957. |**|    Do Activate events
  958. \**/
  959.  
  960. static void Handle_ActivateEvent(WindowPtr updateWindowP)
  961. {
  962. #pragma unused(updateWindowP)
  963. }
  964.  
  965. /**\
  966. |**|    Do OS events
  967. \**/
  968.  
  969. static void Handle_OSEvent(const long message)
  970. {
  971.     if ((message >> 24) == suspendResumeMessage)
  972.     {
  973.         if ((message & resumeFlag) != 0)
  974.             gInBackGround = false;
  975.         else
  976.             gInBackGround = true;
  977.     }
  978.     else if ((message >> 24) == mouseMovedMessage)
  979.     {
  980.         // mouse moved!
  981.     }
  982. }
  983.  
  984. /**\
  985. |**|    Do mouse down in window content
  986. \**/
  987.  
  988. static void Handle_ContentClick(WindowPtr pWindowPtr,const EventRecord* pEventPtr)
  989. {
  990. #pragma unused (pEventPtr)
  991.     if (pWindowPtr != FrontWindow())
  992.     {
  993.         SelectWindow(pWindowPtr);
  994.         //        HiliteWindows();
  995.     }
  996.     else
  997.     {
  998.         gNextTicks = TickCount();                // make it update now
  999.         //        SysBeep(15);
  1000.     }
  1001. }
  1002.  
  1003. static OSStatus Collect_Info(void)
  1004. {
  1005.     MPTaskID    tMPTaskID = kInvalidID;
  1006.     MPProcessID    tMPProcessID = kInvalidID;
  1007.     MPTaskInfo    tMPTaskInfo;
  1008.     OSStatus    anErr = noErr;
  1009.     SInt32         count = 0;
  1010.  
  1011.     while (true)
  1012.     {
  1013.         tMPTaskInfo.version = kMPTaskInfoVersion;
  1014.  
  1015.         // For every kernel process...
  1016.         anErr = MPGetNextProcessID(&tMPProcessID);
  1017.         if (noErr != anErr)
  1018.             break;
  1019.  
  1020.         while (true)
  1021.         {
  1022.             SInt32 index;
  1023.  
  1024.             // For every task of this process...
  1025.             anErr = MPGetNextTaskID(tMPProcessID, &tMPTaskID);
  1026.             if (noErr != anErr)
  1027.                 break;
  1028.  
  1029.             // get the task state (Duh!)
  1030.             anErr = MPExtractTaskState(tMPTaskID, kMPTaskStateTaskInfo, (void*) & tMPTaskInfo);
  1031.             if (noErr != anErr)
  1032.                 break;
  1033.  
  1034.             count++;    // Bump the count
  1035.  
  1036.             // find a task record that matches Proc & Task ID's.
  1037.             for (index = 0; index < gMyTaskRecCount; index++)
  1038.             {
  1039.                 if ((tMPProcessID == gMyTaskRecs[index].fProcID) &&
  1040.                     (tMPTaskID == gMyTaskRecs[index].fTaskID))
  1041.                     break;
  1042.             }
  1043.  
  1044.             // If we didn't find a matching task record...
  1045.             if (index >= gMyTaskRecCount)
  1046.             {    // search for an invalid (unused) task record
  1047.                 for (index = 0; index < gMyTaskRecCount; index++)
  1048.                 {
  1049.                     if (kInvalidID == gMyTaskRecs[index].fTaskID)
  1050.                         break;
  1051.                 }
  1052.             }
  1053.  
  1054.             // If we still haven't found a task record to use...
  1055.             if (index >= gMyTaskRecCount)
  1056.             {    // ... use the last record
  1057.                 index = gMyTaskRecCount;
  1058.                 if (gMyTaskRecCount < kMaxTasks)
  1059.                 {    // and bump the count
  1060.                     gMyTaskRecs[index].fTaskID = kInvalidID;
  1061.                     gMyTaskRecCount++;
  1062.                 }
  1063.             }
  1064.  
  1065.             // if we found a task record to use...
  1066.             if (index < gMyTaskRecCount)
  1067.             {
  1068.                 // ... store the new task record Info
  1069.                 if (gMyTaskRecs[index].fTaskID == kInvalidID)
  1070.                 {
  1071.                     gMyTaskRecs[index].fProcID = tMPProcessID;
  1072.                     gMyTaskRecs[index].fTaskID = tMPTaskID;
  1073.                     gMyTaskRecs[index].fInfo = tMPTaskInfo;
  1074.                 }
  1075.                 gMyTaskRecs[index].fLast = gMyTaskRecs[index].fInfo;
  1076.                 gMyTaskRecs[index].fInfo = tMPTaskInfo;
  1077.                 gMyTaskRecs[index].fValid = true;
  1078.             }
  1079.         }
  1080.     }
  1081.     if ((0 != count) && (kMPInvalidIDErr == anErr))
  1082.         anErr = noErr;
  1083.  
  1084.     return anErr;
  1085. }
  1086.  
  1087. #if APPEARANCE_SAVY
  1088. static void Draw_Info(void)
  1089. {
  1090.  
  1091. }
  1092. #else
  1093. static void Draw_Info(void)
  1094. {
  1095.     Str255 tStr;
  1096.     Rect tRect = gWindowRect;
  1097.     UInt64 schedDelta, cpuTime, last_cpuTime, first_time, sched_time;
  1098.     UInt64 cpuTimeTotal[kMaxCPUs],cpuTimeGrandTotal = 0;
  1099.     UInt64 schedDeltaTotal[kMaxCPUs],schedDeltaGrandTotal = 0;
  1100.     UInt32 preemptions,preemptionsTotal[kMaxCPUs],preemptionsGrandTotal = 0;
  1101.     UInt32 deltaPreemptions,deltaPreemptionsTotal[kMaxCPUs],deltaPreemptionsGrandTotal = 0;
  1102.     UInt32 weight,weightTotal[kMaxCPUs],weightGrandTotal = 0;
  1103.     float percent,percentage,percentTotal[kMaxCPUs],percentGrandTotal = 0;
  1104.     Boolean validCPU[kMaxCPUs];
  1105.     SInt32 index;
  1106.  
  1107.     for (index = 0;index < kMaxCPUs;index++)
  1108.     {
  1109.         cpuTimeTotal[index] = 
  1110.             schedDeltaTotal[index] =
  1111.             percentTotal[index] =
  1112.             preemptionsTotal[index] =
  1113.             deltaPreemptionsTotal[index] =
  1114.             weightTotal[index] = 0;
  1115.             validCPU[index] = 0;
  1116.     }
  1117.  
  1118.     //    tRect.bottom = tRect.top + (kTextSize * 2);
  1119.     tRect.bottom = tRect.top + 20;
  1120.  
  1121.     sprintf((Ptr) tStr, "   ");
  1122.     if (gPreferences.fShowProcID)
  1123.         sprintf((Ptr) tStr, "%s Proc ID ", tStr);
  1124.  
  1125.     if (gPreferences.fShowTaskID)
  1126.         sprintf((Ptr) tStr, "%s Task ID ", tStr);
  1127.  
  1128.     if (gPreferences.fShowName)
  1129.         sprintf((Ptr) tStr, "%sName ", tStr);
  1130.  
  1131.     if (gPreferences.fShowQueue)
  1132.         sprintf((Ptr) tStr, "%sQueue ", tStr);
  1133.  
  1134.     if (gPreferences.fShowCPUTime)
  1135.         sprintf((Ptr) tStr, "%s    cpuTime   ", tStr);
  1136.  
  1137.     if (gPreferences.fShowDeltaCPU)
  1138.         sprintf((Ptr) tStr, "%s  ΔCPU  ", tStr);
  1139.  
  1140.     if (gPreferences.fShowPercent)
  1141.         sprintf((Ptr) tStr, "%s  cpu %% ", tStr);
  1142.  
  1143.     if (gPreferences.fShowPreemptions)
  1144.         sprintf((Ptr) tStr, "%s  Preemptions ", tStr);
  1145.  
  1146.     if (gPreferences.fShowDeltaPreemptions)
  1147.         sprintf((Ptr) tStr, "%s ΔPreemp ", tStr);
  1148.  
  1149.     if (gPreferences.fShowWeight)
  1150.         sprintf((Ptr) tStr, "%s  Weight", tStr);
  1151.  
  1152.     C2PSTR(tStr);
  1153.     RGBForeColor(&blackRGBColor);
  1154.     RGBBackColor(&grayRGBColors[5]);
  1155.  
  1156.     TETextBox(&tStr[1], tStr[0], &tRect, teFlushLeft);
  1157.  
  1158.     OffsetRect(&tRect, 0, 21);
  1159.  
  1160.     for (index = 0; index < gMyTaskRecCount; index++)
  1161.     {
  1162.         if (!gMyTaskRecs[index].fValid)
  1163.             gMyTaskRecs[index].fTaskID = kInvalidID;
  1164.         else if (gMyTaskRecs[index].fTaskID != kInvalidID)
  1165.         {
  1166.             SInt16 lastCPU = kMaxCPUs;
  1167.  
  1168.             RGBForeColor(&blackRGBColor);
  1169.             RGBBackColor(&grayRGBColors[5]);
  1170.  
  1171.             // creationTime time
  1172.             first_time = AbsoluteToMilliseconds(gMyTaskRecs[index].fInfo.creationTime);
  1173.  
  1174.             // current total CPU time
  1175.             cpuTime = AbsoluteToMilliseconds(gMyTaskRecs[index].fInfo.cpuTime);
  1176.  
  1177.             // last total CPU time
  1178.             last_cpuTime = AbsoluteToMilliseconds(gMyTaskRecs[index].fLast.cpuTime);
  1179.  
  1180.             // current scheduled CPU time
  1181.             sched_time = AbsoluteToMilliseconds(gMyTaskRecs[index].fInfo.schedTime);
  1182.  
  1183.             // Compute this interval's CPU percentage based on the last scheduled time.
  1184.             // If the task has not acquired any scheduling intervals, the CPU% is zero.
  1185.  
  1186.             schedDelta = AbsoluteToMilliseconds(gMyTaskRecs[index].fInfo.schedTime) - AbsoluteToMilliseconds(gMyTaskRecs[index].fLast.schedTime);
  1187.  
  1188.             if (schedDelta > 0)
  1189.                 percent = ((cpuTime - last_cpuTime) * 100.0) / schedDelta;// instantaneous CPU %
  1190.             else
  1191.                 percent = 0.0;
  1192.  
  1193.             if (sched_time > first_time)
  1194.                 percentage = 100.0 * cpuTime / (sched_time - first_time);
  1195.             else
  1196.                 percentage = 0.0;
  1197.  
  1198.             // We may have some error in our sampling, so pin it between 0 & 100 %.
  1199.             percent = fmax(fmin(percent, 100.0), 0.0);
  1200.             percentage = fmax(fmin(percentage, 100.0), 0.0);
  1201.  
  1202.             // sprintf((Ptr) tStr,    "  ");
  1203.  
  1204.             if (((gTheEvent.modifiers & optionKey) != optionKey) ||
  1205.                 (gMyTaskRecs[index].fInfo.name != 'idle'))
  1206.             {
  1207.                 tStr[0] = (gMyTaskRecs[index].fInfo.runState == kMPTaskRunning) ? '*' : ' ';
  1208.                 tStr[1] = '\0';
  1209.  
  1210.                 lastCPU = gMyTaskRecs[index].fInfo.lastCPU % kMaxCPUs;
  1211.                 validCPU[lastCPU] = true;
  1212.                 sprintf((Ptr) tStr, "%s%1.1X ", tStr, lastCPU);
  1213.  
  1214.                 if (gPreferences.fShowProcID)
  1215.                     sprintf((Ptr) tStr, "%s%08lx ", tStr, gMyTaskRecs[index].fProcID);
  1216.  
  1217.                 if (gPreferences.fShowTaskID)
  1218.                     sprintf((Ptr) tStr, "%s%08lx ", tStr, gMyTaskRecs[index].fTaskID);
  1219.  
  1220.                 if (gPreferences.fShowName)
  1221.                     sprintf((Ptr) tStr, "%s%.4s ", tStr, &gMyTaskRecs[index].fInfo.name);
  1222.  
  1223.                 if (gPreferences.fShowQueue)
  1224.                     sprintf((Ptr) tStr, "%s%.4s  ", tStr, &gMyTaskRecs[index].fInfo.queueName);
  1225.  
  1226.                 if (gPreferences.fShowCPUTime)
  1227.                     sprintf((Ptr) tStr, "%s%3lld:%02lld:%02lld.%03lld ", tStr, cpuTime / (1000 * 60 * 60),// hours
  1228.                             (cpuTime / (1000 * 60)) % 60,// minutes
  1229.                             (cpuTime / 1000) % 60,    // seconds
  1230.                             cpuTime % 1000);        // thousandths
  1231.  
  1232.                 if (gPreferences.fShowDeltaCPU)
  1233.                     sprintf((Ptr) tStr, "%s%6lldΔ ", tStr, schedDelta);
  1234.  
  1235.                 if (gPreferences.fShowPercent)
  1236.                     sprintf((Ptr) tStr, "%s %5.1f%% ", tStr, percent);
  1237.  
  1238.                 preemptions = gMyTaskRecs[index].fInfo.preemptions;
  1239.                 if (gPreferences.fShowPreemptions)
  1240.                     sprintf((Ptr) tStr, "%s     %8ld ", tStr, preemptions);
  1241.  
  1242.                 deltaPreemptions = gMyTaskRecs[index].fInfo.preemptions - gMyTaskRecs[index].fLast.preemptions;
  1243.                 if (gPreferences.fShowDeltaPreemptions)
  1244.                     sprintf((Ptr) tStr, "%s %6ldΔ ", tStr, deltaPreemptions);
  1245.  
  1246.                 weight = gMyTaskRecs[index].fInfo.weight;
  1247.                 if (gPreferences.fShowWeight)
  1248.                     sprintf((Ptr) tStr, "%s  %6ld ", tStr, weight);
  1249.  
  1250.                 C2PSTR(tStr);
  1251.                 TETextBox(&tStr[1], tStr[0], &tRect, teFlushLeft);
  1252.  
  1253.                 while (gPreferences.fShowBar)
  1254.                 {
  1255.                     float oldPercent = gMyTaskRecs[index].fPercent;
  1256.                     Rect tRect1 = tRect, tRect2, tRect3;
  1257.                     UInt32 width;
  1258.  
  1259.                     tRect1.left += StringWidth(tStr) + 4;
  1260.                     tRect1.right -= 20;
  1261.                     InsetRect(&tRect1, 0, 2);
  1262.  
  1263.                     if (tRect1.left >= tRect1.right)
  1264.                         break;
  1265.  
  1266.                     tRect1.bottom = tRect1.top + 11;
  1267.  
  1268.                     RGBForeColor(&blackRGBColor);
  1269.                     RGBBackColor(&grayRGBColors[3]);
  1270.  
  1271.                     FrameRect(&tRect1);
  1272.                     InsetRect(&tRect1, 1, 1);
  1273.  
  1274.                     width = tRect1.right - tRect1.left;
  1275.  
  1276.                     tRect3 = tRect2 = tRect1;
  1277.  
  1278.                     tRect2.left = tRect1.right = tRect1.left + (width * percent * 0.01f);
  1279.                     tRect3.left = tRect2.right = tRect1.left + (width * fmax(percent, oldPercent) * 0.01f);
  1280. #if 0
  1281.                     {
  1282.                         UInt32 index = 0;
  1283.                         Rect tRect4 = tRect1;
  1284.                         while (tRect4.top < tRect4.bottom)
  1285.                         {
  1286.                             RGBForeColor(&greenRGBColors[index++]);
  1287.                             FrameRect(&tRect4);
  1288.                             InsetRect(&tRect4, 1, 1);
  1289.                         }
  1290.                     }
  1291. #else
  1292.                     {
  1293.                         RGBColor tRGBColorMin = {0x4000,0xC000,0xFFFF};
  1294.                         RGBColor tRGBColorMax = {0xFFFF,0xFFFF,0x1000};
  1295.                         RGBColor tRGBColor = Blend_RGBColors(tRGBColorMin,tRGBColorMax,percent * 0.01f);
  1296.                         if (percent < 100.0f)
  1297.                             RGBForeColor(&tRGBColor);
  1298.                         else
  1299.                             RGBForeColor(&tRGBColorMax);
  1300.                         PaintRect(&tRect1);
  1301.                     }
  1302.  
  1303. #endif 0
  1304.                     if (percent < oldPercent)
  1305.                     {
  1306.  
  1307.                         UInt32 index = 0;
  1308.                         while (tRect2.top < tRect2.bottom)
  1309.                         {
  1310.                             RGBForeColor(&dkGreenRGBColors[index++]);
  1311.                             FrameRect(&tRect2);
  1312.                             InsetRect(&tRect2, 1, 1);
  1313.                         }
  1314.                     }
  1315.  
  1316.                     {
  1317.                         UInt32 index;
  1318.                         for (index = 0; index < 6; index++)
  1319.                         {
  1320.                             RGBForeColor(&grayRGBColors[index]);
  1321.                             FrameRect(&tRect3);
  1322.                             InsetRect(&tRect3, 1, 1);
  1323.                         }
  1324.                         PaintRect(&tRect3);
  1325.                     }
  1326.  
  1327.                     gMyTaskRecs[index].fPercent = percent;
  1328.  
  1329.                     tRect1.right = (tRect1.left += (width * percentage / 100)) + 2;
  1330.  
  1331.                     RGBForeColor(&redRGBColor);
  1332.                     PaintRect(&tRect1);
  1333.  
  1334.                     break;
  1335.                 }
  1336.  
  1337.                 OffsetRect(&tRect, 0, 21);
  1338.  
  1339.                 cpuTimeTotal[lastCPU] += cpuTime;
  1340.                 schedDeltaTotal[lastCPU] += schedDelta;
  1341.                 percentTotal[lastCPU] += percent;
  1342.                 preemptionsTotal[lastCPU] += preemptions;
  1343.                 deltaPreemptionsTotal[lastCPU] += deltaPreemptions;
  1344.                 weightTotal[lastCPU] += weight;
  1345.             }
  1346.             gMyTaskRecs[index].fValid = false;
  1347.         }
  1348.     }
  1349.  
  1350.     if (gPreferences.fShowSubTotals)
  1351.     {
  1352.         RGBForeColor(&blackRGBColor);
  1353.         RGBBackColor(&grayRGBColors[5]);
  1354.  
  1355.         sprintf((Ptr) tStr, "   ");    // 3 spaces
  1356.  
  1357.         if (gPreferences.fShowProcID)
  1358.             sprintf((Ptr) tStr, "%s         ", tStr);
  1359.  
  1360.         if (gPreferences.fShowTaskID)
  1361.             sprintf((Ptr) tStr, "%s         ", tStr);
  1362.  
  1363.         if (gPreferences.fShowName)
  1364.             sprintf((Ptr) tStr, "%s     ", tStr);
  1365.  
  1366.         if (gPreferences.fShowQueue)
  1367.             sprintf((Ptr) tStr, "%s      ", tStr);
  1368.  
  1369.         if (gPreferences.fShowCPUTime)
  1370.             sprintf((Ptr) tStr, "%s============= ", tStr);
  1371.  
  1372.         if (gPreferences.fShowDeltaCPU)
  1373.             sprintf((Ptr) tStr, "%s======= ", tStr);
  1374.  
  1375.         if (gPreferences.fShowPercent)
  1376.             sprintf((Ptr) tStr, "%s======= ", tStr);
  1377.  
  1378.         if (gPreferences.fShowPreemptions)
  1379.             sprintf((Ptr) tStr, "%s============= ", tStr);
  1380.  
  1381.         if (gPreferences.fShowDeltaPreemptions)
  1382.             sprintf((Ptr) tStr, "%s======== ", tStr);
  1383.  
  1384.         if (gPreferences.fShowWeight)
  1385.             sprintf((Ptr) tStr, "%s======== ", tStr);
  1386.  
  1387.         C2PSTR(tStr);
  1388.         TETextBox(&tStr[1], tStr[0], &tRect, teFlushLeft);
  1389.         OffsetRect(&tRect, 0, 21);
  1390.     }
  1391.  
  1392.     for (index = 0; index < kMaxCPUs; index++)
  1393.     {
  1394.         if (validCPU[index])
  1395.         {
  1396.             if (gPreferences.fShowSubTotals)
  1397.             {
  1398.                 sprintf((Ptr) tStr, " %1.1X ", index);
  1399.  
  1400.                 if (gPreferences.fShowProcID)
  1401.                     sprintf((Ptr) tStr, "%s         ", tStr);
  1402.  
  1403.                 if (gPreferences.fShowTaskID)
  1404.                     sprintf((Ptr) tStr, "%s         ", tStr);
  1405.  
  1406.                 if (gPreferences.fShowName)
  1407.                     sprintf((Ptr) tStr, "%s     ", tStr);
  1408.  
  1409.                 if (gPreferences.fShowQueue)
  1410.                     sprintf((Ptr) tStr, "%s      ", tStr);
  1411.  
  1412.                 if (gPreferences.fShowCPUTime)
  1413.                     sprintf((Ptr) tStr, "%s%3lld:%02lld:%02lld.%03lld ",
  1414.                         tStr,
  1415.                         cpuTimeTotal[index] / (1000 * 60 * 60),    // hours
  1416.                         (cpuTimeTotal[index] / (1000 * 60)) % 60,    // minutes
  1417.                         (cpuTimeTotal[index] / 1000) % 60,            // seconds
  1418.                         cpuTimeTotal[index] % 1000);                // thousandths
  1419.  
  1420.                 if (gPreferences.fShowDeltaCPU)
  1421.                     sprintf((Ptr) tStr, "%s%6lldΔ ", tStr, schedDeltaTotal[index]);
  1422.  
  1423.                 if (gPreferences.fShowPercent)
  1424.                     sprintf((Ptr) tStr, "%s %5.1f%% ", tStr, percentTotal[index]);
  1425.  
  1426.                 if (gPreferences.fShowPreemptions)
  1427.                     sprintf((Ptr) tStr, "%s     %8ld ", tStr, preemptionsTotal[index]);
  1428.  
  1429.                 if (gPreferences.fShowDeltaPreemptions)
  1430.                     sprintf((Ptr) tStr, "%s %6ldΔ ", tStr, deltaPreemptionsTotal[index]);
  1431.  
  1432.                 if (gPreferences.fShowWeight)
  1433.                     sprintf((Ptr) tStr, "%s  %6ld ", tStr, weightTotal[index]);
  1434.  
  1435.                 C2PSTR(tStr);
  1436.                 TETextBox(&tStr[1], tStr[0], &tRect, teFlushLeft);
  1437.                 OffsetRect(&tRect, 0, 21);
  1438.             }
  1439.             cpuTimeGrandTotal += cpuTimeTotal[index];
  1440.             schedDeltaGrandTotal += schedDeltaTotal[index];
  1441.             percentGrandTotal += percentTotal[index];
  1442.             preemptionsGrandTotal += preemptionsTotal[index];
  1443.             deltaPreemptionsGrandTotal += deltaPreemptionsTotal[index];
  1444.             weightGrandTotal += weightTotal[index];
  1445.         }
  1446.     }
  1447.  
  1448.     if (gPreferences.fShowTotals)
  1449.     {
  1450.         RGBForeColor(&blackRGBColor);
  1451.         RGBBackColor(&grayRGBColors[5]);
  1452.  
  1453.         sprintf((Ptr) tStr, "   ");    // 3 spaces
  1454.  
  1455.         if (gPreferences.fShowProcID)
  1456.             sprintf((Ptr) tStr, "%s         ", tStr);
  1457.  
  1458.         if (gPreferences.fShowTaskID)
  1459.             sprintf((Ptr) tStr, "%s         ", tStr);
  1460.  
  1461.         if (gPreferences.fShowName)
  1462.             sprintf((Ptr) tStr, "%s     ", tStr);
  1463.  
  1464.         if (gPreferences.fShowQueue)
  1465.             sprintf((Ptr) tStr, "%s      ", tStr);
  1466.  
  1467.         if (gPreferences.fShowCPUTime)
  1468.             sprintf((Ptr) tStr, "%s============= ", tStr);
  1469.  
  1470.         if (gPreferences.fShowDeltaCPU)
  1471.             sprintf((Ptr) tStr, "%s======= ", tStr);
  1472.  
  1473.         if (gPreferences.fShowPercent)
  1474.             sprintf((Ptr) tStr, "%s======= ", tStr);
  1475.  
  1476.         if (gPreferences.fShowPreemptions)
  1477.             sprintf((Ptr) tStr, "%s============= ", tStr);
  1478.  
  1479.         if (gPreferences.fShowDeltaPreemptions)
  1480.             sprintf((Ptr) tStr, "%s======== ", tStr);
  1481.  
  1482.         if (gPreferences.fShowWeight)
  1483.             sprintf((Ptr) tStr, "%s======== ", tStr);
  1484.  
  1485.         C2PSTR(tStr);
  1486.         TETextBox(&tStr[1], tStr[0], &tRect, teFlushLeft);
  1487.  
  1488.         OffsetRect(&tRect, 0, 21);
  1489.  
  1490.         sprintf((Ptr) tStr, "   ");    // 3 spaces
  1491.  
  1492.         if (gPreferences.fShowProcID)
  1493.             sprintf((Ptr) tStr, "%s         ", tStr);
  1494.  
  1495.         if (gPreferences.fShowTaskID)
  1496.             sprintf((Ptr) tStr, "%s         ", tStr);
  1497.  
  1498.         if (gPreferences.fShowName)
  1499.             sprintf((Ptr) tStr, "%s     ", tStr);
  1500.  
  1501.         if (gPreferences.fShowQueue)
  1502.             sprintf((Ptr) tStr, "%s      ", tStr);
  1503.  
  1504.         if (gPreferences.fShowCPUTime)
  1505.             sprintf((Ptr) tStr, "%s%3lld:%02lld:%02lld.%03lld ",
  1506.                 tStr,
  1507.                 cpuTimeGrandTotal / (1000 * 60 * 60),    // hours
  1508.                 (cpuTimeGrandTotal / (1000 * 60)) % 60,    // minutes
  1509.                 (cpuTimeGrandTotal / 1000) % 60,            // seconds
  1510.                 cpuTimeGrandTotal % 1000);                // thousandths
  1511.  
  1512.         if (gPreferences.fShowDeltaCPU)
  1513.             sprintf((Ptr) tStr, "%s%6lldΔ ", tStr, schedDeltaGrandTotal);
  1514.  
  1515.         if (gPreferences.fShowPercent)
  1516.             sprintf((Ptr) tStr, "%s %5.1f%% ", tStr, percentGrandTotal);
  1517.  
  1518.         if (gPreferences.fShowPreemptions)
  1519.             sprintf((Ptr) tStr, "%s     %8ld ", tStr, preemptionsGrandTotal);
  1520.  
  1521.         if (gPreferences.fShowDeltaPreemptions)
  1522.             sprintf((Ptr) tStr, "%s %6ldΔ ", tStr, deltaPreemptionsGrandTotal);
  1523.  
  1524.         if (gPreferences.fShowWeight)
  1525.             sprintf((Ptr) tStr, "%s  %6ld ", tStr, weightGrandTotal);
  1526.  
  1527.         C2PSTR(tStr);
  1528.         TETextBox(&tStr[1], tStr[0], &tRect, teFlushLeft);
  1529.         OffsetRect(&tRect, 0, 21);
  1530.     }
  1531.  
  1532.     RGBBackColor(&grayRGBColors[5]);
  1533.     tRect.bottom = gWindowRect.bottom;
  1534.     EraseRect(&tRect);
  1535.  
  1536.     RGBForeColor(&blackRGBColor);
  1537.     tRect = gWindowRect;
  1538.     tRect.top -= 1;
  1539.     tRect.left -= 1;
  1540.     tRect.right -= 14;
  1541.     tRect.bottom -= 14;
  1542.     FrameRect(&tRect);
  1543.  
  1544.  
  1545. }
  1546. #endif APPEARANCE_SAVY
  1547.  
  1548.  
  1549. //*************************
  1550. //
  1551. // AbsoluteToMilliseconds
  1552. //
  1553. //*************************
  1554.  
  1555. static UInt64 AbsoluteToMilliseconds(const AbsoluteTime t)
  1556. {
  1557.  
  1558.     Nanoseconds nSec;
  1559.     UInt64 oneMillion = 1000000;
  1560.  
  1561.     nSec = AbsoluteToNanoseconds(t);
  1562.  
  1563.     return U64Div(UnsignedWideToUInt64(nSec), oneMillion);
  1564. }
  1565.  
  1566. /**\
  1567. |**|    save_prefs
  1568. \**/
  1569.  
  1570. static OSStatus save_prefs(void)
  1571. {
  1572.     gPreferences.fWindowRect = gWindowRect;
  1573.     if (gWindowPtr)
  1574.     {
  1575.         GrafPtr savePort;
  1576.  
  1577.         GetPort(&savePort);
  1578.         SetPortWindowPort(gWindowPtr);
  1579.  
  1580.         LocalToGlobal((Point *) &gPreferences.fWindowRect.top);
  1581.         LocalToGlobal((Point *) &gPreferences.fWindowRect.bottom);
  1582.  
  1583.         SetPort(savePort);
  1584.     }
  1585.     return WritePreferences(&gPreferences);
  1586. }
  1587.  
  1588. /* ======================================================= */
  1589. /* Routine: Blend_RGBColors */
  1590. /* Purpose: blend two rgb colors according to the frac part of a float */
  1591.  
  1592. static RGBColor Blend_RGBColors(
  1593.     const RGBColor pRGBColorA,
  1594.     const RGBColor pRGBColorB,
  1595.     const float pBlend)
  1596. {
  1597.     RGBColor tRGBColor;
  1598.     SInt32 blend = pBlend;
  1599.     float fracB = pBlend - blend;
  1600.     float fracA = 1.0f - fracB;
  1601.  
  1602.     tRGBColor.red = (pRGBColorA.red * fracA) + (pRGBColorB.red * fracB);
  1603.     tRGBColor.green = (pRGBColorA.green * fracA) + (pRGBColorB.green * fracB);
  1604.     tRGBColor.blue = (pRGBColorA.blue * fracA) + (pRGBColorB.blue * fracB);
  1605.  
  1606.     return tRGBColor;
  1607. }
  1608.  
  1609. #if !TARGET_API_MAC_CARBON
  1610. /**\
  1611. |**|    Zoom_Window
  1612. \**/
  1613.  
  1614. static void Zoom_Window(WindowPtr theWindow,
  1615.                         const short zoomDir,
  1616.                         const short hMax,
  1617.                         const short vMax)
  1618. {
  1619.     Rect *windRect = nil, *zoomRect = nil;
  1620.     Rect globalPortRect, theSect, dGDRect;
  1621.     GDHandle nthDevice, dominantGDevice;
  1622.     long sectArea,
  1623.     greatestArea;
  1624.  
  1625.     if (TrackBox(theWindow, gTheEvent.where, zoomDir))
  1626.     {
  1627.         SetPortWindowPort(theWindow);
  1628. #if ACCESSOR_CALLS_ARE_FUNCTIONS
  1629.         GetPortBounds(GetWindowPort(theWindow),&globalPortRect);
  1630. #else
  1631.         globalPortRect = theWindow->portRect;
  1632. #endif
  1633.         EraseRect(&globalPortRect);        // recommended for cosmetic reasons
  1634.  
  1635.         if (zoomDir == inZoomOut)
  1636.         {
  1637.             /*
  1638.              *    ZoomWindow() is a good basic tool, but it doesn't do everything necessary to
  1639.              *    implement a good human interface when zooming. In fact it's not even close for
  1640.              *    more high-end hardware configurations. We must help it along by calculating an
  1641.              *    appropriate window size and location any time a window zooms out.
  1642.              */
  1643. #if TARGET_API_MAC_CARBON
  1644.             GetWindowBounds(theWindow, kWindowStructureRgn, windRect);
  1645. #else
  1646.             windRect = &(**((WindowPeek)theWindow)->strucRgn).rgnBBox;
  1647. #endif
  1648.             dominantGDevice = nil;
  1649.             if (gHasColorQD)
  1650.             {
  1651.  
  1652.                 /*
  1653.                  *    Color QuickDraw implies the possibility of multiple monitors. This is where
  1654.                  *    zooming becomes more interesting. One should zoom onto the monitor containing
  1655.                  *    the greatest portion of the window. This requires walking the gDevice list.
  1656.                  */
  1657.  
  1658.                 nthDevice = GetDeviceList();
  1659.                 greatestArea = 0;
  1660.                 while (nthDevice != nil)
  1661.                 {
  1662.                     if (TestDeviceAttribute(nthDevice, screenDevice))
  1663.                     {
  1664.                         if (TestDeviceAttribute(nthDevice, screenActive))
  1665.                         {
  1666.                             SectRect(windRect, &(**nthDevice).gdRect, &theSect);
  1667.                             sectArea = (long)RECT_WIDTH(theSect) * (long)RECT_HEIGHT(theSect);
  1668.                             if (sectArea > greatestArea)
  1669.                             {
  1670.                                 greatestArea = sectArea;// save the greatest intersection
  1671.                                 dominantGDevice = nthDevice;// and which device it belongs to
  1672.                             }
  1673.                         }
  1674.                     }
  1675.                     nthDevice = GetNextDevice(nthDevice);
  1676.                 }
  1677.             }
  1678.  
  1679.             /*
  1680.              *    At this point, we know the dimensions of the window we're zooming, and we know
  1681.              *    what screen we're going to put it on. To be more specific, however, we need a
  1682.              *    rectangle which defines the maximum dimensions of the resized window's contents.
  1683.              *    This rectangle accounts for the thickness of the window frame, the menu bar, and
  1684.              *    one or two pixels around the edges for cosmetic compatibility with ZoomWindow().
  1685.              */
  1686.  
  1687.             if (dominantGDevice != nil)
  1688.             {
  1689.                 dGDRect = (**dominantGDevice).gdRect;
  1690.                 if (dominantGDevice == GetMainDevice())// account for menu bar on main device
  1691.                     dGDRect.top += GetMBarHeight();
  1692.             }
  1693.             else
  1694.             {
  1695. #if TARGET_API_MAC_CARBON
  1696.                 BitMap        screenBits;
  1697.  
  1698.                 dGDRect = GetQDGlobalsScreenBits(&screenBits)->bounds;    // if no gDevice, use default monitor
  1699. #else
  1700.                 dGDRect = qd.screenBits.bounds;    // if no gDevice, use default monitor
  1701. #endif TARGET_API_MAC_CARBON
  1702.                 dGDRect.top += GetMBarHeight();
  1703.             }
  1704.  
  1705. #if TARGET_API_MAC_CARBON
  1706.             GetPortBounds(GetWindowPort(theWindow),&globalPortRect);
  1707. #else
  1708.             globalPortRect = theWindow->portRect;
  1709. #endif TARGET_API_MAC_CARBON
  1710.  
  1711.             LocalToGlobal(&topLeft(globalPortRect));// calculate the window's portRect
  1712.             LocalToGlobal(&botRight(globalPortRect));// in global coordinates
  1713.  
  1714.             // account for the window frame and inset it a few pixels
  1715.             dGDRect.left += 2 + globalPortRect.left - windRect->left;
  1716.             dGDRect.top += 2 + globalPortRect.top - windRect->top;
  1717.             dGDRect.right -= 1 + windRect->right - globalPortRect.right;
  1718.             dGDRect.bottom -= 1 + windRect->bottom - globalPortRect.bottom;
  1719.  
  1720.             /*
  1721.              *    Now we know exactly what our limits are, and since there are input parameters
  1722.              *    specifying the dimensions we'd like to see, we can move and resize the zoom
  1723.              *    state rectangle for the best possible results. We have three goals in this:
  1724.              *    1. Display the window entirely visible on a single device.
  1725.              *    2. Resize the window to best represent the dimensions of the document itself.
  1726.              *    3. Move the window as short a distance as possible to achieve #1 and #2.
  1727.              */
  1728. #if TARGET_API_MAC_CARBON
  1729.             GetWindowStandardState(theWindow, zoomRect);
  1730. #else
  1731.             zoomRect = &(**(WStateDataHandle)((WindowPeek)theWindow)->dataHandle).stdState;
  1732. #endif TARGET_API_MAC_CARBON
  1733.  
  1734.             /*
  1735.              *    Initially set the zoom rectangle to the size requested by the input parameters,
  1736.              *    although not smaller than a minimum size. We do this without moving the origin.
  1737.              */
  1738.  
  1739.             zoomRect->right = (zoomRect->left = globalPortRect.left) + hMax;
  1740.             //                                    MAX(hMax, MinWindowWidth(theWindow));
  1741.             zoomRect->bottom = (zoomRect->top = globalPortRect.top) + vMax;
  1742.             //                                    MAX(vMax, MinWindowHeight(theWindow));
  1743.  
  1744.             // Shift the entire rectangle if necessary to bring its origin inside dGDRect.
  1745.             OffsetRect(zoomRect, MAX(dGDRect.left - zoomRect->left, 0), MAX(dGDRect.top - zoomRect->top, 0));
  1746.  
  1747.             /*
  1748.              *    Shift the rectangle up and/or to the left if necessary to accomodate the view,
  1749.              *    and if it is possible to do so. The rectangle may not be moved such that its
  1750.              *    origin would fall outside of dGDRect.
  1751.              */
  1752.  
  1753.             OffsetRect(zoomRect, -PIN(zoomRect->right - dGDRect.right, 0, zoomRect->left - dGDRect.left), -PIN(zoomRect->bottom - dGDRect.bottom, 0, zoomRect->top - dGDRect.top));
  1754.  
  1755.             // Clip expansion to dGDRect, in case view is larger than dGDRect.
  1756.             zoomRect->right = MIN(zoomRect->right, dGDRect.right);
  1757.             zoomRect->bottom = MIN(zoomRect->bottom, dGDRect.bottom);
  1758.         }
  1759.         ZoomWindow(theWindow, zoomDir, false);    // all it needed was a brain transplant
  1760.     }
  1761. }
  1762.  
  1763. /**\
  1764. |**|    Grow_WindowGrid
  1765. \**/
  1766. #define kExtremeNeg -32768
  1767. #define kExtremePos (32767 - 1) // required to address an old region bug, see develop 20 Q&As
  1768.  
  1769. static void Pull_Rect(Rect* startRect);            // prototype
  1770. static void Grow_WindowGrid(WindowPtr theWindow)
  1771. {
  1772.     PenState oldPen;
  1773.     GrafPtr tempWP, WMPort;
  1774.     Rect wideOpen = {kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos};
  1775.     RgnHandle oldRgn = NewRgn();
  1776.     Rect draggingRect;
  1777.  
  1778. #if TARGET_API_MAC_CARBON
  1779.     GetPortBounds(GetWindowPort(theWindow),&draggingRect);
  1780. #else
  1781.     draggingRect = theWindow->portRect;
  1782. #endif TARGET_API_MAC_CARBON
  1783.  
  1784.     GetPort(&tempWP);
  1785.     SetPortWindowPort(theWindow);
  1786.  
  1787.     // normalize my rectangle into the window manager port coordinates
  1788.     LocalToGlobal((Point *) & draggingRect.top);
  1789.     LocalToGlobal((Point *) & draggingRect.bottom);
  1790.  
  1791.     //  go to the WManager port
  1792. #if TARGET_API_MAC_CARBON
  1793.     WMPort = *(GrafPtr*) 0x09DE;
  1794. #else
  1795.     GetWMgrPort(&WMPort);    //•• CALL NOT IN CARBON
  1796. #endif TARGET_API_MAC_CARBON
  1797.     SetPort(WMPort);
  1798.  
  1799.     // save the Window manager pen state since we'll be changing it
  1800.     GetPenState(&oldPen);
  1801.  
  1802.     // localize back
  1803.     GlobalToLocal((Point *) & draggingRect.top);
  1804.     GlobalToLocal((Point *) & draggingRect.bottom);
  1805.  
  1806.     // save the current clip region, and set our wide-open clip
  1807.     GetClip(oldRgn);
  1808.     ClipRect(&wideOpen);
  1809.  
  1810.     // go to the routine below to do the actual dragging
  1811.     Pull_Rect(&draggingRect);
  1812.  
  1813.     // restore the original environment
  1814.     SetClip(oldRgn);
  1815.     SetPenState(&oldPen);
  1816.     DisposeRgn(oldRgn);
  1817.  
  1818.     // now size the window for the returned rect
  1819.     SetPortWindowPort(theWindow);
  1820. #if TARGET_API_MAC_CARBON
  1821.     {
  1822.         Rect tRect;
  1823.         GetPortBounds(GetWindowPort(theWindow),&tRect);
  1824.         InvalWindowRect(theWindow,&tRect);
  1825.     }
  1826. #else
  1827.     InvalWindowRect(theWindow,&theWindow->portRect);
  1828. #endif TARGET_API_MAC_CARBON
  1829.     SizeWindow(theWindow, draggingRect.right - draggingRect.left, draggingRect.bottom - draggingRect.top, true);
  1830.     SetPort(tempWP);
  1831. }
  1832.  
  1833. static void Pull_Rect(Rect* startRect)
  1834. {
  1835.     Rect oldRect;
  1836.     Point endPoint;
  1837.     Boolean hreversed = false;
  1838.     Boolean vreversed = false;
  1839.     short tempH,
  1840.     tempV;
  1841.     short divByGridh,
  1842.     divByGridv;
  1843.  
  1844.     // set up
  1845.     oldRect = *startRect;
  1846.     PenMode(srcXor);                            // So we can rubberband
  1847. #if TARGET_API_MAC_CARBON
  1848.     {
  1849.         Pattern grayPat;
  1850.  
  1851.         GetQDGlobalsGray(&grayPat);
  1852.         PenPat(&grayPat);
  1853.     }
  1854. #else
  1855.     PenPat(&qd.gray);
  1856. #endif TARGET_API_MAC_CARBON
  1857.     FrameRect(startRect);
  1858.     divByGridh = startRect->right;
  1859.     divByGridv = startRect->bottom;
  1860.  
  1861.     while (StillDown())
  1862.     {                                            // Keep doing this as long as the
  1863.         // user keeps the mouse down
  1864.  
  1865.         GetMouse(&endPoint);                    // Current mouse position in local
  1866.  
  1867.         // see if it's on a  grid point
  1868.         tempH = ABS(endPoint.h - divByGridh) / gGridSize.h;
  1869.         tempV = ABS(endPoint.v - divByGridv) / gGridSize.v;
  1870.  
  1871.         // normalize to our grid values. We'll always go outwards as better
  1872.         if ((tempH * gGridSize.h) != ABS(endPoint.h - divByGridh))// shove out based on the remainer
  1873.             endPoint.h = (((endPoint.h) / gGridSize.h) * gGridSize.h) + gGridSize.h;
  1874.         if ((tempV * gGridSize.v) != ABS(endPoint.v - divByGridv))
  1875.             endPoint.v = (((endPoint.v) / gGridSize.v) * gGridSize.v) + gGridSize.v;
  1876.  
  1877.         // If things reversed, we have to make sure that we don't try
  1878.         // and grid the origin point of the drag, cuz that would be weird
  1879.         if (hreversed)
  1880.         {
  1881.             // see if the rectangle flipped first
  1882.             if (endPoint.h > startRect->right)    // they flipped back
  1883.                 hreversed = false;                // and ignore this move
  1884.             else                                // still reversed
  1885.                 startRect->left = endPoint.h;
  1886.         }
  1887.         else
  1888.         {
  1889.             if (endPoint.h < startRect->left)
  1890.                 hreversed = true;
  1891.             else
  1892.                 startRect->right = endPoint.h;
  1893.         }
  1894.         if (vreversed)
  1895.         {
  1896.             // see if it flipped first
  1897.             if (endPoint.v > startRect->bottom)    // they flipped back
  1898.                 vreversed = false;                // and ignore this move
  1899.             else                                // still reversed
  1900.                 startRect->top = endPoint.v;
  1901.         }
  1902.         else
  1903.         {
  1904.             if (endPoint.v < startRect->top)
  1905.                 vreversed = true;
  1906.             else
  1907.                 startRect->bottom = endPoint.v;
  1908.         }
  1909.  
  1910.         if (!EqualRect(startRect, &oldRect))
  1911.         {
  1912.             // redraw the rect only if the mouse moved
  1913.             FrameRect(&oldRect);
  1914.             FrameRect(startRect);                // draw the new rect
  1915.             oldRect = *startRect;
  1916.         }
  1917.     }
  1918.     FrameRect(startRect);
  1919.  
  1920.     PenMode(srcCopy);
  1921. #if TARGET_API_MAC_CARBON
  1922.     {
  1923.         Pattern blackPat;
  1924.  
  1925.         GetQDGlobalsBlack(&blackPat);
  1926.         PenPat(&blackPat);
  1927.     }
  1928. #else
  1929.     PenPat(&qd.black);
  1930. #endif TARGET_API_MAC_CARBON
  1931. }
  1932.  
  1933. /*-------------------------------------------------------------------------------------
  1934.  
  1935.   Drag_WindowGrid- a big nasty function to Drag a window along grid lines.  
  1936.   Note the elegant error handling.  You should change it to make your users happy.
  1937.  
  1938.   You can change the size of the 'grid rects' by changing the value of kIncrement.
  1939.  
  1940. */
  1941. static void Drag_WindowGrid(WindowPtr win,const Point pt)
  1942. {
  1943.     RgnHandle dragRgn, lastDragRgn, insetGray;
  1944.     GrafPtr oldPort, tmpPort;
  1945.     Point currPt, firstMulPoint, lastMulPoint, currMulPoint;
  1946.     Boolean frameHidden;
  1947.     enum {kIncrement = 16, kBorderInset = 4};
  1948.  
  1949.     // Set up our regions - init our variables.
  1950.     dragRgn = NewRgn();
  1951.     lastDragRgn = NewRgn();
  1952.     insetGray = NewRgn();
  1953.     if ((dragRgn == NULL) || (lastDragRgn == NULL) || (insetGray == NULL))
  1954.     {
  1955.         DebugStr("\p|not enough memory- bye!");
  1956.         return;
  1957.     }
  1958.     CopyRgn(GetGrayRgn(), insetGray);
  1959.     if (MemError() != noErr)
  1960.     {
  1961.         DebugStr("\p|not enough memory- bye!");
  1962.         return;
  1963.     }
  1964.  
  1965.     InsetRgn(insetGray, kBorderInset, kBorderInset);
  1966.     frameHidden = false;
  1967.  
  1968.     // Set up a port to draw into, and save off the old
  1969. #if TARGET_API_MAC_CARBON
  1970.     GetPort(&oldPort);
  1971.     tmpPort = CreateNewPort();
  1972.  
  1973.     SetPortVisibleRegion(tmpPort, GetGrayRgn());
  1974.     {
  1975.         Rect tRect;
  1976.  
  1977.         GetRegionBounds(GetGrayRgn(),&tRect);
  1978.         SetPortBounds(tmpPort,&tRect);
  1979.     }
  1980. #else
  1981.     tmpPort = (GrafPtr) NewPtr(sizeof(GrafPort));
  1982.     if (tmpPort == NULL)
  1983.     {
  1984.         DebugStr("\p|not enough memory- bye!");
  1985.         return;
  1986.     }
  1987.     GetPort(&oldPort);
  1988.     OpenPort(tmpPort);
  1989.     CopyRgn(GetGrayRgn(), tmpPort->visRgn);
  1990.     if (MemError() != noErr)
  1991.     {
  1992.         DebugStr("\p|not enough memory- bye!");
  1993.         return;
  1994.     }
  1995.     tmpPort->portRect = (*GetGrayRgn())->rgnBBox;
  1996. #endif TARGET_API_MAC_CARBON
  1997.     SetPort(tmpPort);
  1998.  
  1999.     PenMode(patXor);
  2000. #if TARGET_API_MAC_CARBON
  2001.     {
  2002.         Pattern grayPat;
  2003.  
  2004.         GetQDGlobalsGray(&grayPat);
  2005.         PenPat(&grayPat);
  2006.     }
  2007. #else
  2008.     PenPat(&qd.gray);
  2009. #endif TARGET_API_MAC_CARBON
  2010.  
  2011.     // Set the incoming point to be on a multiple of kIncrement,
  2012.     // to make later calculations easier.
  2013.     currMulPoint.h = pt.h + (kIncrement / 2);
  2014.     currMulPoint.h /= kIncrement;
  2015.     currMulPoint.h *= kIncrement;
  2016.     currMulPoint.v = pt.v + (kIncrement / 2);
  2017.     currMulPoint.v /= kIncrement;
  2018.     currMulPoint.v *= kIncrement;
  2019.  
  2020.     firstMulPoint = lastMulPoint = currMulPoint;
  2021. #if TARGET_API_MAC_CARBON
  2022.     if (noErr != GetWindowRegion(win,kWindowStructureRgn,dragRgn))
  2023. #else
  2024.     CopyRgn(((WindowPeek)win)->strucRgn, dragRgn);
  2025.     if (MemError() != noErr)
  2026. #endif TARGET_API_MAC_CARBON
  2027.     {
  2028.         DebugStr("\p|not enough memory- bye!");
  2029.         return;
  2030.     }
  2031.  
  2032. #if TARGET_API_MAC_CARBON
  2033.     if (noErr != GetWindowRegion(win,kWindowStructureRgn,lastDragRgn))
  2034. #else
  2035.     CopyRgn(((WindowPeek)win)->strucRgn, lastDragRgn);
  2036.     if (MemError() != noErr)
  2037. #endif TARGET_API_MAC_CARBON
  2038.     {
  2039.         DebugStr("\p|not enough memory- bye!");
  2040.         return;
  2041.     }
  2042.  
  2043.     // Draw the first framed region, which will follow the mouse
  2044.     // on the screen
  2045.     FrameRgn(lastDragRgn);
  2046.  
  2047.     while (WaitMouseUp() == true)
  2048.     {
  2049.         // Now track the mouse, and when it moves enough make the framed
  2050.         // region move as well.
  2051.         GetMouse(&currPt);
  2052.  
  2053.         // Set the new point to be on a multiple of kIncrement
  2054.         currMulPoint.h = currPt.h + (kIncrement / 2);
  2055.         currMulPoint.h /= kIncrement;
  2056.         currMulPoint.h *= kIncrement;
  2057.         currMulPoint.v = currPt.v + (kIncrement / 2);
  2058.         currMulPoint.v /= kIncrement;
  2059.         currMulPoint.v *= kIncrement;
  2060.  
  2061.         // Should we be showing the frame region ??
  2062.         if (PtInRgn(currPt, insetGray) == false)
  2063.         {
  2064.             // It's somewhere near the edges, so hide the frame
  2065.             if (frameHidden == false)            // if it's not hidden already, hide it now
  2066.                 FrameRgn(lastDragRgn);
  2067.             frameHidden = true;
  2068.         }
  2069.         else
  2070.         {                                        // else, the frame should be shown if it's hidden
  2071.             if (frameHidden == true)
  2072.             {
  2073.                 FrameRgn(lastDragRgn);
  2074.                 frameHidden = false;
  2075.             }
  2076.         }
  2077.  
  2078.         // Has the mouse moved ?
  2079.         if (!EqualPt(currMulPoint, lastMulPoint))
  2080.         {
  2081.             // The mouse coordinates have changed enough to adjust the window,
  2082.             // so move the frame accordingly
  2083.             OffsetRgn(dragRgn, currMulPoint.h - lastMulPoint.h, currMulPoint.v - lastMulPoint.v);
  2084.  
  2085.             if (frameHidden == false)
  2086.             {
  2087.                 // Only show the frame if we're allowed to.
  2088.                 FrameRgn(dragRgn);
  2089.                 FrameRgn(lastDragRgn);
  2090.             }
  2091.             lastMulPoint = currMulPoint;
  2092.             CopyRgn(dragRgn, lastDragRgn);
  2093.             if (MemError() != noErr)
  2094.             {
  2095.                 DebugStr("\p|not enough memory- bye!");
  2096.                 return;
  2097.             }
  2098.         }
  2099.     }
  2100.  
  2101.     // If frameHidden is true, there's no need to erase the final frame.
  2102.     if (frameHidden == false)
  2103.         FrameRgn(lastDragRgn);
  2104.  
  2105.     if (!EqualPt(lastMulPoint, firstMulPoint) && (frameHidden == false))
  2106.     {
  2107.         // The mouse has moved from its original position and is
  2108.         // somewhere on the screen, so move the window accordingly.
  2109.         Point globalPt, diffPt, contPt = {
  2110.                                           0, 0};
  2111.  
  2112.         // Calculate the difference between the strucRgn's 0, 0 and
  2113.         // the window's content region 0, 0.  Remember that MoveWindow
  2114.         // moves the window's *content* to the coordinate specified, and
  2115.         // we want to move the window's structure to fit in the lastDragRgn
  2116.         SetPortWindowPort(win);
  2117.         // LocalToGlobal works much better when the port is set up...
  2118.         LocalToGlobal(&contPt);
  2119.         SetPort(tmpPort);
  2120. #if TARGET_API_MAC_CARBON
  2121.         {
  2122.             Rect tRect;
  2123.  
  2124.             GetWindowBounds(win, kWindowStructureRgn, &tRect);
  2125.  
  2126.             diffPt.h = contPt.h - tRect.left;
  2127.             diffPt.v = contPt.v - tRect.top;
  2128.  
  2129.             GetRegionBounds(lastDragRgn,&tRect);
  2130.  
  2131.             globalPt.h = tRect.left;
  2132.             globalPt.v = tRect.top;
  2133.         }
  2134. #else
  2135.         diffPt.h = contPt.h - (*((WindowPeek)win)->strucRgn)->rgnBBox.left;
  2136.         diffPt.v = contPt.v - (*((WindowPeek)win)->strucRgn)->rgnBBox.top;
  2137.         globalPt.h = (*lastDragRgn)->rgnBBox.left;
  2138.         globalPt.v = (*lastDragRgn)->rgnBBox.top;
  2139. #endif TARGET_API_MAC_CARBON
  2140.  
  2141.         LocalToGlobal(&globalPt);
  2142.         globalPt.h += diffPt.h;
  2143.         globalPt.v += diffPt.v;
  2144.         MoveWindow(win, globalPt.h, globalPt.v, true);
  2145.     }
  2146.  
  2147.     // Close the port and tear everything down
  2148. #if TARGET_API_MAC_CARBON
  2149.     DisposePort(tmpPort);
  2150. #else
  2151.     ClosePort(tmpPort);
  2152. #endif TARGET_API_MAC_CARBON
  2153.     SetPort(oldPort);
  2154.  
  2155.     DisposeRgn(dragRgn);
  2156.     DisposeRgn(insetGray);
  2157.     DisposeRgn(lastDragRgn);
  2158. }
  2159. #endif !TARGET_API_MAC_CARBON
  2160.  
  2161. #if USE_COLLECTION_TASK
  2162.  
  2163. static Duration TicksToMilliseconds(UInt32 pTicks)
  2164. {
  2165.     return (pTicks * 500 * durationMillisecond / 30);
  2166. }
  2167.  
  2168. OSStatus InfoTask(void *parameter)
  2169. {
  2170.     OSStatus    anErr = noErr;
  2171.     AbsoluteTime expirationTime;
  2172.  
  2173.     (parameter);    // #pragma unused
  2174.  
  2175.     expirationTime = UpTime();
  2176.  
  2177.     while (noErr == anErr)
  2178.     {
  2179.         anErr = Collect_Info();
  2180.         if (noErr != anErr) break;
  2181.  
  2182.         anErr = MPSignalSemaphore(gInfoReadyMPSemaphoreID);
  2183.         if (noErr != anErr) break;
  2184.  
  2185.         // calculate next expriation time
  2186.         expirationTime = AddDurationToAbsolute(TicksToMilliseconds(gPreferences.fInterval),expirationTime);
  2187.  
  2188.         // Now delay until our expiration time.
  2189.         anErr = MPDelayUntil(&expirationTime);
  2190.     }
  2191.     return anErr;
  2192. }
  2193. #endif USE_COLLECTION_TASK
  2194.  
  2195.